package com.binhthuan.catechist.server.bus;

import java.util.List;

import org.hibernate.Criteria;
import org.hibernate.HibernateException;
import org.hibernate.Session;
import org.hibernate.Transaction;
import org.hibernate.criterion.Restrictions;

import com.binhthuan.catechist.server.domain.AbstractObject;
import com.binhthuan.catechist.server.domain.Status;
import com.binhthuan.catechist.server.domain.AttendanceStatus;
import com.binhthuan.catechist.server.domain.ScheduleStatus;
import com.binhthuan.catechist.server.domain.TraineeStatus;
import com.binhthuan.catechist.server.domain.TrainerStatus;
import com.binhthuan.catechist.server.util.HibernateUtil;
import com.binhthuan.catechist.shared.constant.Parameter;

public class StatusBUS extends AbstractBUS {

    public Class<? extends Status> getStatusType(int statusType) {
        Class<? extends Status> cls = null;

        switch (statusType) {
        case Parameter.StatusType.ATTENDANCE_STATUS:
            cls = AttendanceStatus.class;
            break;
        case Parameter.StatusType.TRAINER_STATUS:
            cls = TrainerStatus.class;
            break;
        case Parameter.StatusType.SCHEDULE_STATUS:
            cls = ScheduleStatus.class;
            break;
        case Parameter.StatusType.TRAINEE_STATUS:
            cls = TraineeStatus.class;
            break;
        }

        return cls;
    }

    public <T extends AbstractObject> T getStatusById(int statusType, int id) {
        return get(getStatusType(statusType), id);
    }

    @SuppressWarnings("unchecked")
    public <T extends AbstractObject> T getStatusByName(int statusType, String name) {
        Session session = HibernateUtil.getSessionFactory().openSession();
        Transaction transaction = null;
        T result = null;
        try{
            transaction = session.beginTransaction();
            Criteria crit = session.createCriteria(getStatusType(statusType));
            crit.add(Restrictions.eq("name", name));
            result = (T) crit.uniqueResult();
            
            transaction.commit();
        } catch (HibernateException he) {
            he.printStackTrace();
            transaction.rollback();
        } finally {
            session.close();
        }
        
        return result;
    }

    public boolean isInUsed(int statusType, int id) {
        return true;
    }

    public <T extends AbstractObject> List<T> getAllStatuses(int statusType) {
        return getAll(getStatusType(statusType));
    }

    public <T extends AbstractObject> boolean save(int statusType, T object) {
        Session session = HibernateUtil.getSessionFactory().openSession();
        Transaction transaction = null;
        boolean result = false;
        try {
            transaction = session.beginTransaction();
            session.saveOrUpdate(getStatusType(statusType).getName(), object);
            initializeObjectForUpdate(object);
            transaction.commit();
            result = true;
        } catch (HibernateException he) {
            transaction.rollback();
            throw he;
        } finally {
            session.close();
        }

        return result;
    }

    public <T extends AbstractObject> boolean delete(int statusType, int id) {
        Session session = HibernateUtil.getSessionFactory().openSession();
        Transaction transaction = null;
        boolean result = false;
        try {
            transaction = session.beginTransaction();
            session.delete(getStatusType(statusType).getName(), id);
            transaction.commit();
            result = true;
        } catch (HibernateException he) {
            transaction.rollback();
            throw he;
        } finally {
            session.close();
        }

        return result;
    }
}
